package open.tech.dawn.web.core.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import open.tech.dawn.core.util.SpringContextHolder;
import open.tech.dawn.web.Constants;
import open.tech.dawn.web.core.entity.AuthEntity;
import open.tech.dawn.web.core.entity.LoginUser;
import open.tech.dawn.web.core.error.NoPermissionException;
import open.tech.dawn.web.core.error.TokenExpiredException;
import open.tech.dawn.web.core.properties.JwtProperties;
import open.tech.dawn.web.core.service.IAuthService;
import open.tech.dawn.web.core.service.ILoginUserService;
import open.tech.dawn.web.util.CacheUtil;
import open.tech.dawn.web.util.JwtTokenUtil;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

@Service
@Slf4j
public class AuthServiceImpl implements IAuthService {


    @Resource
    private JwtTokenUtil jwtTokenUtil;


    @Resource
    private JwtProperties jwtProperties;


    private ILoginUserService defaultLoginUserService;

    @PostConstruct
    private void init() {
        defaultLoginUserService = new DefaultLoginUserServiceImpl();
    }


    private ILoginUserService getLoginUserService() {
        try {
            return SpringContextHolder.getBean(ILoginUserService.class);
        } catch (Exception e) {
            log.warn("没有实现open.tech.dawn.web.core.service.ILoginUserService");
            return defaultLoginUserService;
        }
    }


    @Override
    public LoginUser getUser() {
        String token = jwtTokenUtil.getToken();
        String usernameFromToken;
        try {
            usernameFromToken = jwtTokenUtil.getUsernameFromToken(token);
        } catch (Exception e) {
            log.error("解析token失败", e);
            throw new TokenExpiredException();
        }
        if (StrUtil.isEmpty(usernameFromToken)) {
            throw new TokenExpiredException();
        }
        Object attribute = CacheUtil.get(Constants.AUTH_CACHE + usernameFromToken, usernameFromToken);
        if (attribute == null) {
            throw new TokenExpiredException();
        }
        return JSONObject.parseObject(attribute.toString(), LoginUser.class);
    }

    @Override
    public AuthEntity updateToken() {
        LoginUser user = getUser();
        String sessionId = user.getSessionId();
        CacheUtil.remove(Constants.AUTH_CACHE + sessionId);
        return build(sessionId, user);
    }

    private AuthEntity build(String sessionId, LoginUser loginUser) {
        loginUser.setSessionId(sessionId);
        String randomKey = jwtTokenUtil.getRandomKey();
        String token = jwtTokenUtil.generateToken(sessionId, randomKey);
        CacheUtil.put(Constants.AUTH_CACHE + sessionId, sessionId, JSONObject.toJSONString(loginUser), jwtProperties.getExpirationSeconds());
        AuthEntity authEntity = new AuthEntity();
        authEntity.setToken(token);
        authEntity.setExpiration(jwtProperties.getExpirationSeconds());
        return authEntity;
    }

    @Override
    public AuthEntity build(LoginUser loginUser) {
        String sessionId = UUID.randomUUID().toString();
        return build(sessionId, loginUser);
    }

    @Override
    public AuthEntity login(HttpServletRequest request, HttpServletResponse response) {
        return build(getLoginUserService().login(request, response));
    }

    @Override
    public void logout(LoginUser loginUser, HttpServletRequest request, HttpServletResponse response) {
        try {
            if (loginUser != null) {
                CacheUtil.remove(Constants.AUTH_CACHE + loginUser.getSessionId());
            }
        } catch (Exception e) {
            log.error("忽略退出登录报错", e);
        }
        getLoginUserService().logout(loginUser, request, response);
    }


}
